﻿using System;
using System.Collections.Generic;
using Alone.GameObjects.Enemy;
using Alone.Particlesystem;
using AloneLibrary.Particlesystem;
using AloneLibrary.Services.Camera;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XNAnimation;
using XNAnimation.Controllers;

namespace Alone.Handlers
{
	public interface IEnemyHandler
	{
		List<Enemy> Enemies { get; }
	}

	public class EnemyHandler : DrawableGameComponent, IEnemyHandler
	{
		private ICameraHandler camera;
		private IPlayerHandler playerHandler;
		private List<Enemy> enemies = new List<Enemy>();
		private EnemyStateManager enemyStateManager;
		private IEnvironmentHandler environmentHandler;
		private ParticleSystem dirtParticleSystem;
		private Random r = new Random(10);
		private int timeSinceLastUpdate = 0;
		private int updateInterval = 0;
		private int nrOfEnemies = 30;

		public List<Enemy> Enemies
		{
			get { return enemies; }
			set { enemies = value; }
		}

		public EnemyHandler(Game game)
			: base(game)
		{
			game.Services.AddService(typeof(IEnemyHandler), this);
		}

		public override void Initialize()
		{
			enemyStateManager = new EnemyStateManager(Game);
			camera = (ICameraHandler)Game.Services.GetService(typeof(ICameraHandler));
			playerHandler = (IPlayerHandler)Game.Services.GetService(typeof(IPlayerHandler));
			environmentHandler = (IEnvironmentHandler)Game.Services.GetService(typeof(IEnvironmentHandler));
			dirtParticleSystem = new DirtParticleSystem(Game, Game.Content);
			Game.Components.Add(dirtParticleSystem);
			base.Initialize();
		}

		protected override void LoadContent()
		{
			for (int i = 0; i < nrOfEnemies; i++)
			{
				addEnemy();
			}
			base.LoadContent();
		}

		private void addEnemy()
		{
			SkinnedModel model = Game.Content.Load<SkinnedModel>(@"Models\enemy\EnemyBeast");
			Vector3 position, velocity;
			position = new Vector3(r.Next(-3400, 3400), 0, r.Next(-3400, 3400));
			velocity = Vector3.Zero;

			Enemy enemy = new Enemy(
				model,
				new AnimationController(Game.Content.Load<SkinnedModel>(@"Models\enemy\EnemyBeast").SkeletonBones),
				Game.Content.Load<Effect>(@"Effects\AloneEffect"),
				position,
				new Vector2(0, MathHelper.ToRadians(r.Next(0, 360))),
				(float)(r.NextDouble() + 1),
				velocity
			);

			enemy.AnimationController.Speed = 3.0f;
			enemy.AnimationController.LoopEnabled = false;
			enemy.AnimationController.PlayClip(enemy.SkinnedModel.AnimationClips["Emerge"]);
			enemy.AnimationController.PlaybackMode = PlaybackMode.Forward;

			enemy.Position.Y = this.environmentHandler.HeightMap.GetHeight(enemy.Position);
			enemy.Available = true;

			enemies.Add(enemy);
		}

		public override void Update(GameTime gameTime)
		{
			timeSinceLastUpdate += gameTime.ElapsedGameTime.Milliseconds;
			if (timeSinceLastUpdate >= updateInterval)
			{
				enemyStateManager.checkStatesAndUpdateEnemies(enemies, playerHandler.Players);
				foreach (Enemy enemy in enemies)
				{
					if (playerHandler.Player.isColliding(enemy) && timeSinceLastUpdate > 1000f)
					{
						playerHandler.Player.decHealth(1);
					}
					enemy.Position.Y = this.environmentHandler.HeightMap.GetHeight(enemy.Position);

					switch (enemy.AnimationController.AnimationClip.Name)
					{
						case "Walk":
							enemy.AnimationController.PlayClip((enemy.SkinnedModel.AnimationClips["Walk"]));
							break;
						case "Emerge":
							{
								dirtParticleSystem.AddParticle(enemy.Position, Vector3.Zero);
								if (enemy.AnimationController.HasFinished)
								{
									enemy.AnimationController.CrossFade((enemy.SkinnedModel.AnimationClips["Walk"]), TimeSpan.FromSeconds(0.2));
									enemy.AnimationController.LoopEnabled = true;
									enemy.AnimationController.Speed = 1f;
								}
								break;
							}
					}
					enemy.AnimationController.Update(gameTime.ElapsedGameTime, Matrix.Identity);
				}

				if (enemies.Count < nrOfEnemies)
				{
					addEnemy();
				}

				base.Update(gameTime);
				timeSinceLastUpdate -= updateInterval;
			}
		}

		public override void Draw(GameTime gameTime)
		{
			dirtParticleSystem.SetCamera(camera.View, camera.Projection);

			foreach (Enemy enemy in enemies)
			{
				if (enemy.Available)
				{
					if (this.playerHandler.Player.viewFrustum.Intersects(enemy.BoundingSphere))
					{
						enemy.Draw(gameTime, camera);
						//BoundingSphereRenderer.Render(enemy.BoundingSphere, GraphicsDevice, camera.View, camera.Projection, Color.Red);
					}
				}
			}

			base.Draw(gameTime);
		}
	}
}
